package org.hepeng.fabric.gateway.contract.proxy;


import org.apache.commons.pool2.KeyedObjectPool;
import org.hepeng.fabric.gateway.pool.FabricGatewayKeyHolder;
import org.hepeng.fabric.gateway.pool.FabricGatewayObject;
import org.hepeng.fabric.gateway.pool.GatewayKey;
import org.springframework.beans.factory.BeanFactory;

import java.util.Objects;

/**
 * @author he peng
 * @date 2022/3/24
 */
public class FabricGatewayObjectHolder {

    private static BeanFactory beanFactory;

    private static KeyedObjectPool<GatewayKey, FabricGatewayObject> gatewayPool;

    private static final InheritableThreadLocal<FabricGatewayObject> FABRIC_GATEWAY_THREAD_LOCAL = new InheritableThreadLocal<>();

    public static void set(FabricGatewayObject fgo) {
        FABRIC_GATEWAY_THREAD_LOCAL.set(fgo);
    }

    public static FabricGatewayObject current() {
        FabricGatewayObject fabricGatewayObject = FABRIC_GATEWAY_THREAD_LOCAL.get();
        if (Objects.isNull(fabricGatewayObject)) {
            if (Objects.nonNull(gatewayPool)) {
                try {
                    fabricGatewayObject = gatewayPool.borrowObject(FabricGatewayKeyHolder.current());
                    set(fabricGatewayObject);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            } else {
                gatewayPool = beanFactory.getBean(KeyedObjectPool.class);
                current();
            }
        }
        return FABRIC_GATEWAY_THREAD_LOCAL.get();
    }

    public static FabricGatewayObject remove() {
        FabricGatewayObject fabricGatewayObject = FABRIC_GATEWAY_THREAD_LOCAL.get();
        if (Objects.nonNull(fabricGatewayObject)) {
            try {
                gatewayPool.returnObject(fabricGatewayObject.getKey() , fabricGatewayObject);
                FABRIC_GATEWAY_THREAD_LOCAL.remove();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return fabricGatewayObject;
    }

    public static BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public static void setBeanFactory(BeanFactory beanFactory) {
        FabricGatewayObjectHolder.beanFactory = beanFactory;
    }

    public static KeyedObjectPool<GatewayKey, FabricGatewayObject> getGatewayPool() {
        return gatewayPool;
    }

    public static void setGatewayPool(KeyedObjectPool<GatewayKey, FabricGatewayObject> gatewayPool) {
        FabricGatewayObjectHolder.gatewayPool = gatewayPool;
    }
}
